package com.story.modular.app.controller;

import com.google.gson.JsonObject;
import com.story.common.constant.state.ManagerStatus;
import com.story.common.exception.BizExceptionEnum;
import com.story.common.exception.BussinessException;
import com.story.common.persistence.dao.UserMapper;
import com.story.common.persistence.form.*;
import com.story.common.persistence.model.User;
import com.story.core.base.controller.BaseController;
import com.story.core.log.LogManager;
import com.story.core.log.factory.LogTaskFactory;
import com.story.core.shiro.ShiroKit;
import com.story.core.shiro.ShiroUser;
import com.story.modular.system.dao.UserMgrDao;
import com.story.modular.system.factory.UserFactory;
import com.story.modular.system.transfer.UserDto;
import com.story.util.ReturnObject;
import com.story.util.SendSmsUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.http.HttpResponse;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.annotation.Resource;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;

import static com.story.core.support.HttpKit.getIp;

/**
 * @author Pyx
 * @PACKAGE_NAME : com.story.modular.app.controller
 * @FileName: AppLoginController
 * @date 2020/5/7 14:25
 */
@RestController
@Api(value = "第二批 app登录", tags = "第二批 app登录")
public class AppLoginController extends BaseController {
    @Resource
    private UserMgrDao managerDao;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private UserMapper userMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @ApiOperation("app登录")
    @RequestMapping(value = "/appLogin", method = RequestMethod.POST)
    @ResponseBody
    public Object login(@RequestBody LoginForm loginForm) {
        String username = loginForm.getUsername();
        String password = loginForm.getPassword();
        User theUser = managerDao.getByName(username);
        if (theUser == null) {
            throw new BussinessException(BizExceptionEnum.NO_THIS_USER);
        }
        String salt = theUser.getSalt();
        String s = ShiroKit.md5(password, salt);
        if (s.equals(theUser.getPassword())) {
            Subject currentUser = ShiroKit.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(username, password.toCharArray());
            currentUser.login(token);
            ShiroUser shiroUser = ShiroKit.getUser();
            super.getSession().setAttribute("shiroUser", shiroUser);
            super.getSession().setAttribute("username", shiroUser.getAccount());
            return ReturnObject.ok();
        } else {
            throw new BussinessException(BizExceptionEnum.OLD_PWD_NOT_RIGHT);
        }
    }

    @ApiOperation("发送验证码")
    @RequestMapping(value = "/app/getSms", method = RequestMethod.POST)
    @ResponseBody
    public Object getSms(@RequestBody SmsForm smsForm) throws Exception {
        String phoneNum = smsForm.getPhoneNum();
        String random = SendSmsUtil.sendPhoneSms(phoneNum);
        if (redisTemplate.hasKey(phoneNum)) {
            redisTemplate.delete(phoneNum);
        }
        if (redisTemplate.hasKey(phoneNum + "count")) {
            Integer count = Integer.valueOf(redisTemplate.opsForValue().get(phoneNum + "count"));
//            if (count >= 5) {
//                return ReturnObject.error("超出发送限制");
//            }
            redisTemplate.delete(phoneNum + "count");
            redisTemplate.opsForValue().set(phoneNum + "count", String.valueOf(count + 1), 60 * 60 * 12, TimeUnit.SECONDS);
        } else {
            redisTemplate.opsForValue().set(phoneNum + "count", String.valueOf(1), 60 * 60 * 12, TimeUnit.SECONDS);
        }
        redisTemplate.opsForValue().set(phoneNum, random, 60 * 5, TimeUnit.SECONDS);
        return ReturnObject.ok("发送成功");
    }

    @ApiOperation("app验证码登录")
    @RequestMapping(value = "/app/appSmsLogin", method = RequestMethod.POST)
    @ResponseBody
    public Object appSmsLogin(@RequestBody LoginSmsForm loginSmsForm) throws IOException {
        String phone = loginSmsForm.getPhone();
        String code = loginSmsForm.getCode();
        String redisCode = stringRedisTemplate.opsForValue().get(phone);
        if (code.equals(redisCode)) {
            User user = managerDao.getByNameOrPhone(phone);
            if (user == null) {
                return ReturnObject.error("用户不存在");
            }
            String remark = managerDao.getByBase64(user.getId()).get("remark").toString();
            BASE64Decoder decoder = new BASE64Decoder();
            remark = new String(decoder.decodeBuffer(remark));
            Subject currentUser = ShiroKit.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(user.getName(), remark.toCharArray());
            currentUser.login(token);
            ShiroUser shiroUser = ShiroKit.getUser();
            super.getSession().setAttribute("shiroUser", shiroUser);
            super.getSession().setAttribute("username", shiroUser.getAccount());
        } else {
            return ReturnObject.error("验证码错误");
        }
        return ReturnObject.ok("登陆成功");
    }


    @ApiOperation("app注册")
    @RequestMapping(value = "/app/appSmsLog", method = RequestMethod.POST)
    @ResponseBody
    public Object appSmsLog(@RequestBody LogForm logForm) {
        String phone = logForm.getPhone();
        String code = logForm.getCode();
        String username = logForm.getUsername();
        String password = logForm.getPassword();
        String redisCode = stringRedisTemplate.opsForValue().get(phone);
        if (code.equals(redisCode)) {
            User theUser = managerDao.getByAccount(username);
            if (theUser != null) {
                throw new BussinessException(BizExceptionEnum.USER_ALREADY_REG);
            }
            User phoneUser = managerDao.getByNameOrPhone(phone);
            if (phoneUser != null) {
                throw new BussinessException(BizExceptionEnum.USER_ALREADY_REG);
            }
            UserDto user = new UserDto();
            user.setAccount(username);
            user.setName(username);
            user.setPhone(phone);
            user.setSalt(ShiroKit.getRandomSalt(5));
            user.setPassword(ShiroKit.md5(password, user.getSalt()));
            user.setStatus(ManagerStatus.OK.getCode());
            user.setCreatetime(new Date());
            Integer insert = this.userMapper.insert(UserFactory.createUser(user));
            Integer id = managerDao.getByName(user.getAccount()).getId();
            String encode = new BASE64Encoder().encode(password.getBytes());
            managerDao.insertDtoApp(id, encode);
            return ReturnObject.ok("注册成功");
        } else {
            return ReturnObject.error("验证码错误");
        }
    }

    @ApiOperation("修改密码 需要登录")
    @RequestMapping(value = "/app/appUpPwd", method = RequestMethod.POST)
    @ResponseBody
    public Object appUpPwd(@RequestBody ForgetForm forgetForm) {
        String newPassword = forgetForm.getNewPassword();
        String oldPassword = forgetForm.getOldPassword();
        String code = forgetForm.getCode();
        String username = super.getSession().getAttribute("username").toString();
        User theUser = managerDao.getByAccount(username);
        if (theUser == null) {
            throw new BussinessException(BizExceptionEnum.NO_THIS_USER);
        }
        String redisCode = stringRedisTemplate.opsForValue().get(theUser.getPhone());
        if (code.equals(redisCode)) {
            String oldMd5 = ShiroKit.md5(oldPassword, theUser.getSalt());
            if (theUser.getPassword().equals(oldMd5)) {
                String newMd5 = ShiroKit.md5(newPassword, theUser.getSalt());
                theUser.setPassword(newMd5);
                theUser.updateById();
                return ReturnObject.ok("修改成功");
            } else {
                throw new BussinessException(BizExceptionEnum.OLD_PWD_NOT_RIGHT);
            }
        } else {
            return ReturnObject.error("验证码错误");
        }
    }

}
